#include <jni.h>
#include <string>
#include <android/log.h>

extern "C" {
//解码
#include "libavcodec/avcodec.h"
//封装格式处理
#include "libavformat/avformat.h"
//像素处理
#include "libswscale/swscale.h"
//重采样
#include "libswresample/swresample.h"

}

#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,  "Mirror", __VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,  "Mirror", __VA_ARGS__)

jstring getConfiguration(JNIEnv *env, jclass);

void audioPlayer(JNIEnv *env, jclass, jstring);

void initFFmpegLog(JNIEnv *env, jclass);

// 这里是java调用C的存在Native方法的类路径
static const char *const classPath = "com/mirror/application/jni/Jni";

static const JNINativeMethod gMethods[] = {
        {"getConfiguration", "()Ljava/lang/String;",  (void *) getConfiguration},
        {"audioPlayer",      "(Ljava/lang/String;)V", (void *) audioPlayer},
        {"initFFmpegLog",    "()V",                   (void *) initFFmpegLog},
};

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL; //注册时在JNIEnv中实现的，所以必须首先获取它

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) { //从JavaVM获取JNIEnv，一般使用1.4的版本
        return -1;
    }
    // 获取映射的java类
   jclass myClass = env->FindClass(classPath);
    if (myClass == NULL) {
        return -1;
    }
    // 通过RegisterNatives方法动态注册
    if (env->RegisterNatives(myClass, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
        return -1;
    }
    LOGI("JNI_OnLoad End");
    return JNI_VERSION_1_4; //这里很重要，必须返回版本，否则加载会失败。
}

JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return;
    }
    // 拿到 JNIEnv后就可以做一些释放资源的操作了

    LOGI("JNI_OnUnload End");
}

static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vl) {
    static int print_prefix = 1;
    static char prev[1024];
    char line[1024];
    av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);
    strcpy(prev, line);
    if (level <= AV_LOG_ERROR) {
        LOGE("%s", line);
    } else {
        LOGI("%s", line);
    }
}

jstring getConfiguration(JNIEnv *env, jclass) {
    const char *configuration = (char *) (avcodec_configuration());
    return env->NewStringUTF(configuration);
}

void initFFmpegLog(JNIEnv *env, jclass) {
    av_log_set_callback(ffmpeg_log_callback);
}

void audioPlayer(JNIEnv *env, jclass, jstring path_jstr) {
    const char *path_cstr = env->GetStringUTFChars(path_jstr, false);
}
